package com.nkym.wypan.utils;/*
 * @ClassName JwtUtils
 * @Desc TODO
 * @Author 19637
 * @Date 2023/6/8 10:20
 * @Version 1.0
 */


import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.nkym.wypan.enums.ResponseStatus;
import com.nkym.wypan.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Map;
import java.util.Optional;


@Slf4j
public class JwtUtils {


    private static final String secret = "wqhjhtq6";
    private static final String UID_CLAIM = "uid";
    private static final String SHARE_ID_CLAIM = "shareId";
    private static final String CREATE_TIME = "createTime";

    public static String createToken(Long uid) {
        String token = JWT.create().withClaim("uid", uid)
                .withClaim(CREATE_TIME, new Date())
                .sign(Algorithm.HMAC256(secret));
        return token;
    }

    public static String createShareToken(Long shareId) {
        //token 7天有效
        String token = JWT.create().withClaim("shareId", shareId)
                .withClaim(CREATE_TIME, new Date())
                .withExpiresAt(DateUtil.offsetDay(new Date(), 7))
                .sign(Algorithm.HMAC256(secret));
        return token;
    }

    public static Map<String, Claim> verifyUserToken(String token) {
        try {
            JWTVerifier build = JWT.require(Algorithm.HMAC256(secret)).build();
            DecodedJWT verify = build.verify(token);
            Map<String, Claim> claims = verify.getClaims();
            return claims;
        } catch (Exception e) {
            log.info("decode token error,token :{}", token, e);
            throw new BusinessException(ResponseStatus.USER_VERIFY_FAIL);
        }
    }

    public static Map<String, Claim> verifyShareToken(String token) {
        try {
            JWTVerifier build = JWT.require(Algorithm.HMAC256(secret)).build();
            DecodedJWT verify = build.verify(token);
            Map<String, Claim> claims = verify.getClaims();
            return claims;
        } catch (Exception e) {
            log.info("decode token error,token :{}", token, e);
            throw new BusinessException(ResponseStatus.VERIFY_CODE_INVALID);
        }
    }

    /**
     * 根据Token获取uid
     *
     * @param token
     * @return uid
     */
    public static Long getUidOrNull(String token) {
        return Optional.ofNullable(verifyUserToken(token))
                .map(map -> map.get(UID_CLAIM))
                .map(Claim::asLong)
                .orElse(null);
    }

    public static Long getShareIdOrNull(String token) {
        return Optional.ofNullable(verifyShareToken(token))
                .map(map -> map.get(SHARE_ID_CLAIM))
                .map(Claim::asLong)
                .orElse(null);
    }

    public static void main(String[] args) {
//        String token = createToken(1L);
//        System.out.println(token);
//        System.out.println(verifyToken(" eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImNyZWF0ZVRpbWUiOjE2ODYyMDU0NDR9.meRQxdMSrnkBUq-mvxYVapFnyFqOUyRpLNXe0Er7Cfc".trim()));
//        System.out.println(getUidOrNull("            eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImNyZWF0ZVRpbWUiOjE2ODYyMDU0NDR9.meRQxdMSrnkBUq-mvxYVapFnyFqOUyRpLNXe0Er7Cfc"));

//        String token = testCreateToken(1L);
//        System.out.println(token);
        Long uidOrNull = getUidOrNull(
                "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImNyZWF0ZVRpbWUiOjE2OTI0MTUwMDQsImV4cCI6MTY5MjQxNTAwN30._aTa10oqr9bfxJPnN7HKv1iYBmOkWLgijlzjpk84OLs"
        );
        System.out.println(uidOrNull);

    }

    private static String testCreateToken(Long uid) {
        String token = JWT.create().withClaim("uid", uid)
                .withClaim(CREATE_TIME, new Date())
                .withExpiresAt(DateUtil.offsetSecond(new Date(), 3))
                .sign(Algorithm.HMAC256(secret));
        return token;
    }
}
